#include <crt_msghdr.h>
#include <crt_memory.h>

#if (TARGET_OS == OS_WINDOWS)

#pragma comment(lib,"ws2_32.lib")
#include <errno.h>
#include <stdlib.h>
#include <winsock2.h>


ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
{

	DWORD rcvd;
	int ret;
	DWORD dwFlags;
	INT fromlen;
	WSABUF *buf = NULL;
	unsigned int i;

	if (msg->msg_controllen != 0)
	{
		errno = ENOSYS;
		return -1;
	}

	if (msg->msg_iovlen > IOV_MAX)
	{
		errno = EINVAL;
		return -1;
	}

	buf = heap_malloc(msg->msg_iovlen * sizeof (*buf));
	if (buf == NULL)
		return -1;

	for (i = 0; i < msg->msg_iovlen; i++)
	{
		buf[i].len = msg->msg_iov[i].iov_len;
		buf[i].buf = msg->msg_iov[i].iov_base;
	}

	dwFlags = flags;
	fromlen = msg->msg_namelen;

	if (fromlen)
		ret = WSARecvFrom(fd, buf, msg->msg_iovlen, &rcvd, &dwFlags,
		msg->msg_name, &fromlen, NULL, NULL);
	else
		ret = WSARecv(fd, buf, msg->msg_iovlen, &rcvd, &dwFlags,
		NULL, NULL);

	heap_free(buf);

	if (ret == 0)
	{
		msg->msg_namelen = fromlen;
		msg->msg_flags = dwFlags;
		return rcvd;
	}

	switch (WSAGetLastError())
	{
	case WSAEWOULDBLOCK:
		errno = EAGAIN;
		break;
	}
	return -1;
}


ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
{
	WSABUF *buf = NULL;
	DWORD sent;
	unsigned int i;
	int ret;


	if (msg->msg_controllen != 0)
	{
		errno = ENOSYS;
		return -1;
	}

	if (msg->msg_iovlen > IOV_MAX)
	{
		errno = EINVAL;
		return -1;
	}

	buf = heap_malloc(msg->msg_iovlen * sizeof (*buf));
	if (buf == NULL)
		return -1;

	for (i = 0; i < msg->msg_iovlen; i++)
	{
		buf[i].len = msg->msg_iov[i].iov_len;
		buf[i].buf = (void *)msg->msg_iov[i].iov_base;
	}


	ret = WSASendTo(fd, buf, msg->msg_iovlen, &sent, flags,
		msg->msg_name, msg->msg_namelen, NULL, NULL);


	heap_free(buf);

	if (ret == 0)
		return sent;

	switch (WSAGetLastError())
	{
	case WSAEWOULDBLOCK:
		errno = EAGAIN;
		break;
	}
	return -1;
}

#endif



